Amazon API Gatewayのパフォーマンスオプションを理解する
ども、大瀧です。
APIを統合するAWSの新サービス、API Gatewayを社内総出 *1で触っています。今回はAPI Gatewayのパフォーマンスに関する仕組みと設定をご紹介します。
API Gatewayのロケーション
API GatewayはAPIサーバーのリバースプロキシとして動作するサービスのため、API Gateway自身がボトルネックになるようなアーキテクチャは望ましくありません。API Gatewayを実際に触っていると端々に"CloudFront"というキーワードが見かけられ、ForumでAWSの中の人がさらりと"API GatewayのバックエンドはCloudFrontを活用している"と公言している *2ので、API GatewayのベースアーキテクチャとしてCloudFrontのスケーラビリティが得られる、と考えて良さそうです。
CloudFrontは、世界数十カ所のエッジロケーションと呼ばれるデータセンターで提供され、DNSレイテンシーレコードによりクライアントの最寄りのエッジロケーションに自動で接続されるようになっています。API Gatewayの場合はどうでしょうか。API Gatewayは現在、バージニア北部、オレゴン、アイルランドの3リージョンで展開とAWS公式ブログにありますが、実際に日本からAPI Invoke URLにアクセスすると、3リージョンで作った全てのAPI Gatewayで以下のようにカリフォルニアのエッジロケーションのDNSレコードが返ってきます。
バージニア北部リージョンのInvoke URL
$ host XXXXXXXXXX.execute-api.us-east-1.amazonaws.com XXXXXXXXXX.execute-api.us-east-1.amazonaws.com has address 54.192.117.77 XXXXXXXXXX.execute-api.us-east-1.amazonaws.com has address 54.192.117.60 : $ host 54.192.117.77 77.117.192.54.in-addr.arpa domain name pointer server-54-192-117-77.sfo9.r.cloudfront.net. $
オレゴンリージョンのInvoke URL
$ host YYYYYYYYYY.execute-api.us-west-2.amazonaws.com YYYYYYYYYY.execute-api.us-west-2.amazonaws.com has address 54.230.144.160 YYYYYYYYYY.execute-api.us-west-2.amazonaws.com has address 54.230.145.154 : $ host 54.230.144.160 160.144.230.54.in-addr.arpa domain name pointer server-54-230-144-160.sfo4.r.cloudfront.net. $
アイルランドリージョンのInvoke URL
$ host ZZZZZZZZZZ.execute-api.eu-west-1.amazonaws.com ZZZZZZZZZZ.execute-api.eu-west-1.amazonaws.com has address 54.192.144.151 ZZZZZZZZZZ.execute-api.eu-west-1.amazonaws.com has address 216.137.36.69 : $ host 54.192.144.151 151.144.192.54.in-addr.arpa domain name pointer server-54-192-144-151.sfo4.r.cloudfront.net.
この挙動は、CloudFrontのDistributionでPrice ClassをUse Only US and Europe
に設定する場合と同じだったりします(日本からの最寄りのエッジロケーションが、恐らく太平洋ケーブルを介したカリフォルニアなのでしょう)。ですので、API GatewayのAPIを作成するリージョンは、パフォーマンスの面ではあまり大きな影響はないかもしれません。また、東京リージョンに展開されるときはCloudFrontのPrice Classの区分にあわせてアジア3リージョンに同時展開されるのではないでしょうか。
ちなみに、現時点での日本からのレイテンシーは概ね100ms超程度ですので、パフォーマンスが要求される用途でAPI Gatewayを利用するのは厳しいかもしれません。Endpoint URL(API Gatewayのオリジン)が日本だとさらに太平洋を往復することにもなります。
また、CloudFrontを利用しているということから、現時点ではAPI GatewayにVPC関連の設定は一切見当たりません。VPC内にInvoke URLが設定できるとオンプレミスからVPN/Direct Connectで接続する社内向けAPIにも活用できそうなので、その辺りは今後のアップデートに期待しましょう。
APIキャッシュ
API Gatewayのパフォーマンスオプションの一つとして、APIキャッシュが利用できます。その名の通り、Endpoint URLからのレスポンスをAPI Gatewayでキャッシュし、2回目以降の同じリクエストに対してキャッシュをクライアントに返送する仕組みです。キャッシュ設定は、キャッシュ容量とTTL(キャッシュ期限)の2つがあります。キャッシュ容量に応じて課金が発生することと、TTLは先にキャッシュ容量を設定、反映させて初めて設定画面が出るようになることに注意しましょう。
キャッシュ容量の設定画面
Stageの設定画面の[Settings]タブにあります。[Enable API cache]のチェックをオンにし、[Cache capacity]からキャッシュ容量を選択、[Save Changes]ボタンで決定します。
しばらく待ち、[Cache status]がAVAILABLE
になったらOKです。
TTLは、Stageのツリーを展開してMethodをクリックしたメソッドの設定画面の[Cache]タブにあります。
既定で300秒(5分)です。キャッシュが効いているかどうかは、CloudWatchメトリクスで確認します。API GatewayのCloudWatchメトリクスは既定で無効なのでStageの設定画面の[Settings]タブで有効化しましょう。
CloudWatchでは、API GatewayのメトリクスはカスタムメトリクスのApiGateway
ネームスペース(最近Backplane
ネームスペースから変更されました)として確認できます。
こんな感じで、CacheHitCount
とCacheMissCount
でヒット率を比較します。
今回は画像だとちょっと読み取りづらいですが、ひたすら同じInvoke URLにリクエストを送ったのでCacheMissCount
が5分間隔で1
、その他は全てCacheHitCount
としっかりキャッシュが効いていることが見て取れました。
なお、CloudFrontでのキャッシュヒット確認の常套手段であるレスポンスヘッダのX-Cache
は、API Gatewayでは常にMiss from cloudfront
になるため判別手段としては利用できません。
スロットリング
もう一つのパフォーマンスオプションとしてスロットリングがあります。API GatewayのStage毎に同時アクセス数 *3を制限する機能です。トークンバケットアルゴリズムに基づく、「バースト上限(Burst Limit)」と「レート(Rate)」の2つの設定を組み合わせます。ドキュメントには既定でどちらも1
RPSが設定されるとあるのですが、実際に試すともう少しアクセスが許容されるので定かではないです。
どちらかの制限を超えるとレスポンスヘッダが429 Too Many Requests
、レスポンスボディのmessage
はnull
になります。
設定は、Stage画面の[Settings]タブの[Throttling Settings]にあります。(以下は10RPS/10RPSで設定した例)
ちなみに、動作確認のためにab
やhttperf
、siege
といったベンチマークツールを利用しようとしたのですが、API GatewayのSSL/TLSハンドシェイクがTLSv1.2を強要するようで、軒並みハンドシェイクに失敗しエラーになってしまいました。フォーラムでも報告があります。これらのツールで上手くアクセスできるオプションを知っている方がいれば教えてください!で、今回はcurl
を連続実行するシェルスクリプトを組んで試してみました。
#!/bin/bash NUM=1 while : do if [ $NUM -gt 100 ]; then break; fi (curl https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/MyTestStage/greet; echo)& NUM=$((NUM + 1)) done
今回はバースト上限が10なので、多めの100アクセスでどうなるかの実験です。
$ ./curls.bash {"message":"Hello from AWS Lambda!"}{"message":"Hello from AWS Lambda!"} {"message":"Hello from AWS Lambda!"} {"message":"Hello from AWS Lambda!"} : {"message": "null"} :
時折{"message": "null"}
が返ってくる感じで、制限がかかっている様子がわかります。素朴な実装ですが、スクリプトを少し変更し&
を取ってシーケンシャルなアクセスにしてみたり、ループの合間にsleep 1
を挟んでリクエスト間隔を調整すると制限の特性が見えてくると思います。
なお、今回は前述のキャッシュ設定と組み合わせてスロットリングを試してみました。様子としては先にスロットリングの制限がかかって、許可されるとキャッシュ有無が判定されるロジックのようです。本来、スロットリングはキャッシュ元を保護するための仕組みだと思うので、判定順が逆でもいいのかなぁと思ったりしました。
また、Integration TypeがLambda Functionの場合リクエストのタイミングで毎回Lambdaの起動がキックされるため、負荷テストの計測が難しい場合もあると思います。そういったときには今回のキャッシュ設定を有効にすると良いでしょう(さっきと言っていることがずれてますがw)。
まとめ
API Gatewayのロケーションの分析とパフォーマンスに関する2つのオプションをご紹介しました。いずれも、API Gatewayの目的の一つであるAPIの安定運用に役立つオプションであることがご理解いただけたのではないでしょうか。
参考URL
脚注
- ちょっと誇大表現 ↩
- AWS Developer Forums: Custom Domains: Pricing the same as ... ↩
- 厳密にはRPS(Requests per Second) ↩